<?php
/**
 * Wokerman启动服务
*/

namespace houze;

use Workerman\Worker;

class Server {    
    /**
	 * 启动实例
	*/
    private $service;
    /**
     * 服务类型
    */
    private $server_type;
    /**
     * 配置
    */
    private $config;
    
    /**
     * 应用启动入口
    */
    public function start($server, $option) {
        if ($option == '-d') {
            \houze\Config::set('server.daemonize', true);
        }
        $config = \houze\Config::get('server');
        $this->server_type = $server;
        // SSL配置存储
        $ssl_context = [
            'ssl' => $config['ssl']
        ];
        // 加入路由初始化
        switch ($this->server_type) {
            case 'http':
                $this->service = new \Workerman\Worker('http://'. $config['host'] . ':' . $config['port'], $ssl_context);
            break;
            case 'websocket':
                $this->service = new \Workerman\Worker('websocket://'. $config['host'] . ':' . $config['port'], $ssl_context);
            break;
            case 'rpc':
                $this->service = new \Workerman\Worker('text://'. $config['host'] . ':' . $config['port'], $ssl_context);
            break;
            case 'tcp':
                $this->service = new \Workerman\Worker('text://'. $config['host'] . ':' . $config['port'], $ssl_context);
            break;
        }
        // 启动类型写入配置项
        \houze\Config::set('server.houze_service_type', $this->server_type);
        // 记录server实例
        \houze\Config::set('houze_context.server', $this->service);
        $this->config = $config;
         // 注入配置
        $this->service = $this->seConfig($config, $this->service);
        // 挂载核心业务
        $this->mount_event();
        // 进行事件绑定
        $this->event_binding();
    }

    /**
     * 挂载核心业务
    */
    private function mount_event() {
        // 挂载DAO连接池
        \houze\MountEvent::WorkerStart_MysqlStart();
        // 挂载Redis连接池
        \houze\MountEvent::WorkerStart_RedisStart();
        // 挂载MongoDb连接池
        \houze\MountEvent::WorkerStart_MongoDbStart();
        // 挂载RabbitMQ连接池
        \houze\MountEvent::WorkerStart_RabbitMqStart();
        // 挂载memcache连接池
        \houze\MountEvent::WorkerStart_MemcacheStart();
        // 载入内存缓存组件
        \houze\cache\parts\Memory::run();
        // 自动热重载
        \houze\MountEvent::Reload();
        // ES节点嗅探
        \houze\MountEvent::ElasticsearchNodeSniff();
    }

    /**
     * 事件绑定
    */
    protected function event_binding() {
        # 监听进程启动事件
        $this->service->onWorkerStart = [$this->ioc('onWorkerStart'), 'run'];
        # 监听进程重启事件
        $this->service->onWorkerReload = [$this->ioc('onWorkerReload'), 'run'];
        # 监听进程连接事件
        $this->service->onConnect = [$this->ioc('onConnect'), 'run'];
        # 监听进程消息事件
        $this->service->onMessage = [$this->ioc('onMessage', $this->service, $this->config), 'run'];
        # 监听进程关闭事件
        $this->service->onClose = [$this->ioc('onClose'), 'run'];
        # 监听进程缓冲事件
        $this->service->onBufferFull = [$this->ioc('onBufferFull'), 'run'];
        # 监听进程缓冲完成事件
        $this->service->onBufferDrain = [$this->ioc('onBufferDrain'), 'run'];
        # 监听进程连接错误事件
        $this->service->onError = [$this->ioc('onError'), 'run'];
        
        \houze\StartRecord::server_event();
        
        if($this->config['is_global']){
            // 启动内存共享服务
            new \Workerman\GlobalData\Server('127.0.0.1', $this->config['global_port']);
        }
        
        # 启动服务
        Worker::runAll();
    }

    /**
     * 构造回调事件的new对象
    */
    private function ioc($event, ...$argc) {
        $class = '\event\\'.$this->server_type.'\\'.$event;
        if ($event == 'onMessage') {
            if (!isset($this->config['is_onMessage']) || $this->config['is_onMessage'] != true) {
                # 关闭系统分包流程
                $class = '\event\\server\\'.$event;
            }
        }
        $reflection = new \ReflectionClass($class);
        return $reflection->newInstanceArgs($argc);
    }

    // --------------------------- 工具 --------------------------
    /**
     * 初始化配置
    */
    private function seConfig($config, $server) {
        # WSS配置
        $server->count = $config['count'];
        $server->name = $config['name'];
        $server->protocol = $config['protocol'];
        $server->transport = $config['transport'];
        $server->reusePort = $config['reuse_port'];
        $server->reload = $config['reload'];

        Worker::$daemonize = $config['daemonize'];
        Worker::$pidFile = $config['worker_pid_file'];
        Worker::$logFile = $config['log_file'];

        // 配置HTTPS
        if ($config['ssl']['local_cert'] && $config['ssl']['local_pk']) {
            $server->transport = 'ssl';
        }

        return $server;
    }
}